package com.kyb.servlet;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.kyb.config.Env;
import com.kyb.entity.Department;
import com.kyb.entity.User;
import com.kyb.service.DepartmentServcie;
import com.kyb.service.UserService;
import com.kyb.util.AddressListRegister;
import com.kyb.util.AuthHelper;
import com.kyb.util.DingTalkEncryptException;
import com.kyb.util.DingTalkEncryptor;
import com.kyb.util.DingTalkUtil;

import org.apache.log4j.Logger;
import org.junit.Test;

/**
 * <p>
 * 通讯录事件回调
 * <p>
 * 
 * @version 1.0
 * @author li_hao
 * @date 2017年12月21日
 */
@WebServlet("/callbackreceive")
public class CallBackServlet extends HttpServlet {

	private static final long serialVersionUID = -1785796919047156450L;
	public static final Logger LOG = Logger.getLogger(CallBackServlet.class);
	public CallBackServlet() {
		super();
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) {
		doGet(request, response);
	}

	/*
	 * 接收钉钉服务器的回调数据
	 * 
	 */
	@Test
	protected void doGet(HttpServletRequest request, HttpServletResponse response) {

		try {
			/** url中的签名 **/
			String msgSignature = request.getParameter("signature");
			/** url中的时间戳 **/
			String timeStamp = request.getParameter("timestamp");
			/** url中的随机字符串 **/
			String nonce = request.getParameter("nonce");
			/** 取得JSON对象中的encrypt字段 **/
			String encrypt = "";

			/** 获取post数据包数据中的加密数据 **/
			ServletInputStream sis = request.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(sis));
			String line = null;
			StringBuilder sb = new StringBuilder();
			while ((line = br.readLine()) != null) {
				sb.append(line);
			}
			JSONObject jsonEncrypt = JSONObject.parseObject(sb.toString());
			encrypt = jsonEncrypt.getString("encrypt");

			String decodeEncrypt = decodeEncrypt(msgSignature, timeStamp, nonce, encrypt); // 密文解密
			JSONObject decodeEncryptJson = JSONObject.parseObject(decodeEncrypt);

			String eventType = decodeEncryptJson.getString("EventType"); // 回调类型
			JSONArray userJSONArr = (JSONArray) decodeEncryptJson.get("UserId");
			JSONArray deptJSONArr = (JSONArray) decodeEncryptJson.get("DeptId");
			String res = "success"; // res是需要返回给钉钉服务器的字符串，一般为success;"check_create_suite_url"和"check_update_suite_url"事件为random字段;(具体请查看文档或者对应eventType的处理步骤)
			//关闭Http日志
			System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog");
			System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true");
			System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient", "stdout");
			// 根据不同的回调类型，进行相应的操作
			switch (eventType) {
			case AddressListRegister.USER_ADD_ORG:
				// 钉钉通讯录增加用户
				String insertUserInfo = "insertUserInfo";
				doUseInfo(userJSONArr, insertUserInfo);
				break;
			case AddressListRegister.USER_MODIFY_ORG:
				// 通讯录用户更改
				String updateUserInfo = "updateUserInfo";
				doUseInfo(userJSONArr, updateUserInfo);
				break;
			case AddressListRegister.USER_LEAVE_ORG:
				// 通讯录用户离职
				String deleteUserInfo = "deleteUserInfo";
				doUseInfo(userJSONArr, deleteUserInfo);
				break;
			case AddressListRegister.ORG_DEPT_CREATE:
				// 通讯录企业部门创建
				String insertDeptInfo = "insertDeptInfo";
				doDeptInfo(deptJSONArr, insertDeptInfo);
				break;
			case AddressListRegister.ORG_DEPT_MODIFY:
				// 通讯录企业部门修改
				String updateDeptInfo = "updateDeptInfo";
				doDeptInfo(deptJSONArr, updateDeptInfo);
				break;
			case AddressListRegister.ORG_DEPT_REMOVE:
				// 通讯录企业部门删除
				String deleteDeptInfo = "deleteDeptInfo";
				doDeptInfo(deptJSONArr, deleteDeptInfo);
				break;
			case AddressListRegister.CHECK_URL:
				// 测试回调接口事件类型
				LOG.info("测试回调接口！");
				break;
			default:
				break;
			}
			response.getWriter().append(codeEncrypt(res, timeStamp, nonce).toString()); // 返回加密后的数据
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 根据id操作用户信息
	 * 
	 * @param userJSONArr
	 * @param userMethod
	 * @throws Exception
	 */
	private static void doUseInfo(JSONArray userJSONArr, String userMethod) throws Exception {
		String accesstoken = "";
		try {
			accesstoken = AuthHelper.getAccessToken(Env.CORP_ID, Env.CORP_SECRET);
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		UserService userService = new UserService();
		Set<String> setUid = new HashSet<String>();
		for (int j = 0; j < userJSONArr.size(); j++) {
			// 得到就是一个一个的id
			String userid = (String) userJSONArr.get(j);
			User us1 = null;
			// 转换为json对象
			if(!("deleteUserInfo").equals(userMethod)) {
				JSONObject obj2 = userService.getUser(accesstoken, userid);
				us1 = JSONObject.toJavaObject(obj2, User.class);
			}
			// 调用方法
			switch (userMethod) {
			case "insertUserInfo":
				userService.insertUserInto(us1, setUid);
				break;
			case "updateUserInfo":
				userService.updateUserInfo(us1);
				break;
			case "deleteUserInfo":
				userService.deleteUserInfo( userid);
			default: // do something
				break;
			}
		}
	}

	/**
	 * 部门信息操作
	 * @param deptJSONArr
	 * @param deptMethod
	 * @throws Exception
	 */
	private static void doDeptInfo(JSONArray deptJSONArr, String deptMethod) throws Exception {
		String accesstoken = "";
		try {
			accesstoken = AuthHelper.getAccessToken(Env.CORP_ID, Env.CORP_SECRET);
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		DepartmentServcie departmentServcie = new DepartmentServcie();
		Department dept = null;
		JSONObject obj = null;
		for (int i = 0; i < deptJSONArr.size(); i++) {
			String deptId = String.valueOf(deptJSONArr.get(i));
			// 转换为json对象
			if(!("deleteDeptInfo").equals(deptMethod)) {
				obj = departmentServcie.getDepartmentDetail(accesstoken, deptId);
			}
			
			
			JSONObject callBack = DingTalkUtil.getCallBack(accesstoken);
			LOG.info("查询注册事件：" + callBack);
			
			
			// 将json放入实体类
			dept = JSONObject.toJavaObject(obj, Department.class);
			// 调用方法
			switch (deptMethod) {
			case "insertDeptInfo":
				departmentServcie.insertDeptInfo(dept);
				break;
			case "updateDeptInfo":
				departmentServcie.updateDeptInfo(dept);
				
				break;
			case "deleteDeptInfo":
				departmentServcie.deleteDeptInfo(deptId);
				break;
			default: // do something
				break;
			}
		}
	}

	/**
	 * 创建加密/解密 类
	 * 
	 * @return
	 */
	public DingTalkEncryptor createDingTalkEncryptor() {
		DingTalkEncryptor dingTalkEncryptor = null; // 加密方法类
		try {
			dingTalkEncryptor = new DingTalkEncryptor(AddressListRegister.TOKEN, AddressListRegister.AES_KEY,
					AddressListRegister.CORPID); // 创建加解密类
		} catch (DingTalkEncryptException e) {
			e.printStackTrace();
		}
		return dingTalkEncryptor;
	}

	/**
	 * encrypt解密
	 * 
	 * @param msgSignature
	 * @param timeStamp
	 * @param nonce
	 * @param encrypt
	 *            密文
	 * @return decodeEncrypt 解密后的明文
	 */
	public String decodeEncrypt(String msgSignature, String timeStamp, String nonce, String encrypt) {
		String decodeEncrypt = null;
		try {
			decodeEncrypt = createDingTalkEncryptor().getDecryptMsg(msgSignature, timeStamp, nonce, encrypt); // encrypt解密
		} catch (DingTalkEncryptException e) {
			e.printStackTrace();
		}
		return decodeEncrypt;
	}

	/**
	 * 对返回信息进行加密
	 * 
	 * @param res
	 * @param timeStamp
	 * @param nonce
	 * @return
	 */
	public JSONObject codeEncrypt(String res, String timeStamp, String nonce) {
		long timeStampLong = Long.parseLong(timeStamp);
		Map<String, String> jsonMap = null;
		try {
			jsonMap = createDingTalkEncryptor().getEncryptedMap(res, timeStampLong, nonce); // jsonMap是需要返回给钉钉服务器的加密数据包
		} catch (DingTalkEncryptException e) {
			//System.out.println(e.getMessage());
			e.printStackTrace();
		}
		JSONObject json = new JSONObject();
		json.putAll(jsonMap);
		return json;
	}
	
	/***
	 * 注册回调
	 * 
	 * @throws Exception
	 */
	@Test
	public void registerCallBack() throws Exception {
		String accesstoken = AuthHelper.getAccessToken(Env.CORP_ID, Env.CORP_SECRET);
		String token = AddressListRegister.TOKEN;
		String aesKey = AddressListRegister.AES_KEY;
		String callBackUrl = "http://47.99.51.37:8068/dingdata_to_mysql/callbackreceive";
		
		
		List<String> listStr = new ArrayList<String>();
		listStr.add("user_add_org");
		listStr.add("user_modify_org");
		listStr.add("user_leave_org");

		listStr.add("org_dept_create");
		listStr.add("org_dept_modify");
		listStr.add("org_dept_remove");
		
		JSONObject registerCallBack = DingTalkUtil.registerCallBack(accesstoken, listStr, token, aesKey, callBackUrl);
		System.out.println("注册事件返回：" + registerCallBack);

		System.out.println("accesstoken"+accesstoken);
		JSONObject callBack = DingTalkUtil.getCallBack(accesstoken);
		System.out.println("查询注册事件：" + callBack);

	}

}